(function (window, T) {
    var event = T.event = {};


    /**
     * 事件对象构造器，屏蔽浏览器差异的事件类
     * @name event.EventArg
     * @class
     * @grammar event.EventArg(event[, win])
     * @param {Event}   event   事件对象
     * @param {Window}  [win]   窗口对象，默认为window
     * @meta standard
     * @remark 1.1.0开始支持
     * @see event.get
     */
    event.EventArg = function (event, win) {
        win = win || window;
        event = event || win.event;
        var doc = win.document;
        
        this.target = /** @type {Node} */ (event.target) || event.srcElement;
        this.keyCode = event.which || event.keyCode;
        for (var k in event) {
            var item = event[k];
            // 避免拷贝preventDefault等事件对象方法
            if ('function' != typeof item) {
                this[k] = item;
            }
        }
        
        if (!this.pageX && this.pageX !== 0) {
            this.pageX = (event.clientX || 0) 
                            + (doc.documentElement.scrollLeft 
                                || doc.body.scrollLeft);
            this.pageY = (event.clientY || 0) 
                            + (doc.documentElement.scrollTop 
                                || doc.body.scrollTop);
        }
        this._event = event;
    };

    /**
     * 阻止事件的默认行为
     * @name preventDefault
     * @grammar eventArgObj.preventDefault()
     * @returns {event.EventArg} EventArg对象
     */
    event.EventArg.prototype.preventDefault = function () {
        if (this._event.preventDefault) {
            this._event.preventDefault();
        } else {
            this._event.returnValue = false;
        }
        return this;
    };

    /**
     * 停止事件的传播
     * @name stopPropagation
     * @grammar eventArgObj.stopPropagation()
     * @returns {event.EventArg} EventArg对象
     */
    event.EventArg.prototype.stopPropagation = function () {
        if (this._event.stopPropagation) {
            this._event.stopPropagation();
        } else {
            this._event.cancelBubble = true;
        }
        return this;
    };

    /**
     * 停止事件
     * @name stop
     * @grammar eventArgObj.stop()
     * @returns {event.EventArg} EventArg对象
     */
    event.EventArg.prototype.stop = function () {
        return this.stopPropagation().preventDefault();
    };

    /**
     * 获取扩展的EventArg对象
     * @name event.get
     * @function
     * @grammar event.get(event[, win])
     * @param {Event} event 事件对象
     * @param {window} [win] 触发事件元素所在的window
     * @meta standard
     * @see event.EventArg
     *             
     * @returns {EventArg} 扩展的事件对象
     */
    event.get = function (event, win) {
        return new event.EventArg(event, win);
    };

    /**
     * 获取事件对象
     * @name event.getEvent
     * @function
     * @param {Event} event event对象，目前没有使用这个参数，只是保留接口。by dengping.
     * @grammar event.getEvent()
     * @meta standard
     * @return {Event} event对象.
     */

    event.getEvent = function(event) {
        if (window.event) {
            return window.event;
        } else {
            var f = arguments.callee;
            do { //此处参考Qwrap框架 see http://www.qwrap.com/ by dengping
                if (/Event/.test(f.arguments[0])) {
                    return f.arguments[0];
                }
            } while (f = f.caller);
            return null;
        }
    };

    /**
     * 事件监听器的存储表
     * @private
     * @meta standard
     */
    event._listeners = event._listeners || [];



    /**
     * 为目标元素添加事件监听器
     * @name event.on
     * @function
     * @grammar event.on(element, type, listener)
     * @param {HTMLElement|string|window} element 目标元素或目标元素id
     * @param {string} type 事件类型
     * @param {Function} listener 需要添加的监听器
     * @remark
     * 
    1. 不支持跨浏览器的鼠标滚轮事件监听器添加<br>
    2. 改方法不为监听器灌入事件对象，以防止跨iframe事件挂载的事件对象获取失败
        
     * @shortcut on
     * @meta standard
     * @see event.un
     * @returns {HTMLElement|window} 目标元素
     */
    event.on = /**@function*/function (element, type, listener) {
        type = type.replace(/^on/i, '');
        element = dom._g(element);

        var realListener = function (ev) {
                // 1. 这里不支持EventArgument,  原因是跨frame的事件挂载
                // 2. element是为了修正this
                listener.call(element, ev);
            },
            lis = event._listeners,
            filter = event._eventFilter,
            afterFilter,
            realType = type;
        type = type.toLowerCase();
        // filter过滤
        if(filter && filter[type]){
            afterFilter = filter[type](element, type, realListener);
            realType = afterFilter.type;
            realListener = afterFilter.listener;
        }
        
        // 事件监听器挂载
        if (element.addEventListener) {
            element.addEventListener(realType, realListener, false);
        } else if (element.attachEvent) {
            element.attachEvent('on' + realType, realListener);
        }
      
        // 将监听器存储到数组中
        lis[lis.length] = [element, type, listener, realListener, realType];
        return element;
    };

    // 声明快捷方法
    on = event.on;

    /**
     * 为目标元素移除事件监听器
     * @name event.un
     * @function
     * @grammar event.un(element, type, listener)
     * @param {HTMLElement|string|window} element 目标元素或目标元素id
     * @param {string} type 事件类型
     * @param {Function} listener 需要移除的监听器
     * @shortcut un
     * @meta standard
     * @see event.on
     *             
     * @returns {HTMLElement|window} 目标元素
     */
    event.un = function (element, type, listener) {
        element = dom._g(element);
        type = type.replace(/^on/i, '').toLowerCase();
        
        var lis = event._listeners, 
            len = lis.length,
            isRemoveAll = !listener,
            item,
            realType, realListener;
        
        //如果将listener的结构改成json
        //可以节省掉这个循环，优化性能
        //但是由于un的使用频率并不高，同时在listener不多的时候
        //遍历数组的性能消耗不会对代码产生影响
        //暂不考虑此优化
        while (len--) {
            item = lis[len];
            
            // listener存在时，移除element的所有以listener监听的type类型事件
            // listener不存在时，移除element的所有type类型事件
            if (item[1] === type
                && item[0] === element
                && (isRemoveAll || item[2] === listener)) {
                realType = item[4];
                realListener = item[3];
                if (element.removeEventListener) {
                    element.removeEventListener(realType, realListener, false);
                } else if (element.detachEvent) {
                    element.detachEvent('on' + realType, realListener);
                }
                lis.splice(len, 1);
            }
        }
        
        return element;
    };

})(window, T);